package com.houdoudou.bean;

import java.security.Key;  
import java.security.SecureRandom;  
  
import javax.crypto.Cipher;  
import javax.crypto.SecretKey;  
import javax.crypto.SecretKeyFactory;  
import javax.crypto.spec.PBEKeySpec;  
import javax.crypto.spec.PBEParameterSpec;  
 
public class PasswordUtil {  
  
    /**  
     * JAVA6支持以下任意一种算法  
14.     * PBEWITHMD5ANDDES  
15.     * PBEWITHMD5ANDTRIPLEDES  
16.     * PBEWITHSHAANDDESEDE  
17.     * PBEWITHSHA1ANDRC2_40  
18.     * PBKDF2WITHHMACSHA1  
19.     * */   
 
   /** 
    * 定义使用的算法为:PBEWITHMD5andDES算法 
    */  
  public static final String ALGORITHM = "PBEWithMD5AndDES";  
  
   /** 
    * 定义迭代次数为1000次 
     */  
   private static final int ITERATIONCOUNT = 1000;  
   private static final String PASSWORD="hahaalessio";
   private static final String STRSALT="12345678";  //注意，这里只能是8位。
   private static final byte[] SALT = STRSALT.getBytes() ; 
  
    /** 
     * 盐长度必须为8字节  
    *  
    * @return byte[] 盐值 
     * */  
   public static byte[] getSalt() throws Exception {  
       //实例化安全随机数  
       SecureRandom random = new SecureRandom();  
        //产出盐  
        return random.generateSeed(8);  
   }  
 
    /** 
45.    * 根据PBE密码生成一把密钥 
46.     *  
47.     * @param password 
48.     *            生成密钥时所使用的密码 
49.     * @return Key PBE算法密钥 
50.     * */  
   private static Key getPBEKey(String password) throws Exception {  
       // 实例化使用的算法  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);  
        // 设置PBE密钥参数    
        PBEKeySpec keySpec = new PBEKeySpec(password.toCharArray());  
        // 生成密钥  
       SecretKey secretKey = keyFactory.generateSecret(keySpec);  
 
       return secretKey;  
   }  
 
   /** 
63.     * 加密明文字符串 
64.     *  
65.     * @param plaintext 
66.     *            待加密的明文字符串 
67.     * @param password 
68.     *            生成密钥时所使用的密码 
69.     * @param salt 
70.     *            盐值 
71.     * @return 加密后的密文字符串 
72.     * @throws Exception 
73.     */  
   public static String encrypt(String plaintext) throws Exception {  
 
       Key key = getPBEKey(PASSWORD);  
  
       PBEParameterSpec parameterSpec = new PBEParameterSpec(SALT, ITERATIONCOUNT);  
 
       Cipher cipher = Cipher.getInstance(ALGORITHM);  
  
        cipher.init(Cipher.ENCRYPT_MODE, key, parameterSpec);  
 
      byte encipheredData[] = cipher.doFinal(plaintext.getBytes());  
  
       return bytesToHexString(encipheredData);  
   }  
 
    /** 
90.     * 解密密文字符串 
91.     *  
92.     * @param ciphertext 
93.     *           待解密的密文字符串 
94.     * @param password 
95.     *            生成密钥时所使用的密码(如需解密,该参数需要与加密时使用的一致) 
96.     * @param salt 
97.     *            盐值(如需解密,该参数需要与加密时使用的一致) 
98.     * @return 解密后的明文字符串 
99.     * @throws Exception 
100.     */  
   public static String decrypt(String ciphertext) throws Exception {  
 
       Key key = getPBEKey(PASSWORD);  
  
        PBEParameterSpec parameterSpec = new PBEParameterSpec(SALT, ITERATIONCOUNT);  
 
       Cipher cipher = Cipher.getInstance(ALGORITHM);  
  
       cipher.init(Cipher.DECRYPT_MODE, key, parameterSpec);  
  
       byte[] passDec = cipher.doFinal(hexStringToBytes(ciphertext));  
  
       return new String(passDec);  
   }  
 
  /** 
117.     * 将字节数组转换为十六进制字符串 
118.     * @param src 字节数组 
119.     * @return 
120.     */  
   public static String bytesToHexString(byte[] src) {  
        StringBuilder stringBuilder = new StringBuilder("");  
       if (src == null || src.length <= 0) {  
            return null;  
        }  
       for (int i = 0; i < src.length; i++) {  
            int v = src[i] & 0xFF;  
            String hv = Integer.toHexString(v);  
           if (hv.length() < 2) {  
                stringBuilder.append(0);  
            }  
            stringBuilder.append(hv);  
        }  
        return stringBuilder.toString();  
    }  
  
   /** 
138.     * 将十六进制字符串转换为字节数组 
139.     *  
140.     * @param hexString 十六进制字符串 
141.     * @return 
142.     */  
    public static byte[] hexStringToBytes(String hexString) {  
        if (hexString == null || hexString.equals("")) {  
            return null;  
        }  
       hexString = hexString.toUpperCase();  
       int length = hexString.length() / 2;  
       char[] hexChars = hexString.toCharArray();  
        byte[] d = new byte[length];  
        for (int i = 0; i < length; i++) {  
            int pos = i * 2;  
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));  
        }  
        return d;  
    }  
     private static byte charToByte(char c) {  
       return (byte) "0123456789ABCDEF".indexOf(c);  
    }  
}  
